package com.wchat.serviceimpl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wchat.dataobject.MyMessage;
import com.wchat.repository.MyMessageRepository;
import com.wchat.service.MessageService;
import com.wchat.service.UserService;
import com.wchat.utils.SpringContextHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.socket.server.standard.SpringConfigurator;

import javax.annotation.Resource;
import javax.swing.*;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutionException;

@Slf4j
@Component
@Scope("prototype")
@ServerEndpoint(value="/websocketTest/{userId}", configurator = SpringContextHelper.class)
//@ServerEndpoint(value="/websocketTest/{userId}")
public class ChatService {

    @Autowired
    private MessageService messageService;

    //统计在线人数
    private static int onlineCount = 0;

    //用本地线程保存session
    //private static ThreadLocal<Session> sessions = new ThreadLocal<Session>();

    //保存所有连接上的session
    private  Map<String, Session> sessionMap = new HashMap<>();

    private static CopyOnWriteArraySet<ChatService> sessionSet = new CopyOnWriteArraySet<ChatService>();


    private static Map<String, ChatService> clients = new ConcurrentHashMap<String, ChatService>();


    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        onlineCount--;
    }


    private static ConcurrentHashMap<Integer, ChatService> webSocketMap = new ConcurrentHashMap<Integer, ChatService>();
    // 当前会话,属于websocket的session
    private Session session;
    // 聊天信息
    private  String userId; //userId
    private Integer toUser;// 接收人
    private String myselfNickName;// 聊天信息


    //连接时执行.
    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) throws IOException {
        log.info("上线用户id为{}",userId);
        this.userId = userId;      // 用户id
        this.session = session;    // session
        //this.myselfNickName = myselfNickName;  // 初始化数据
        // webSocketMap.put(, this);//当前用户的websocket
        clients.put(userId, this);
        //sessions.set(session);
        addOnlineCount();
        sessionMap.put(userId, session);  //  存储用户的session和userId
        System.out.println("【" + session.getId() + "】连接上服务器======当前在线人数【" + getOnlineCount() + "】");
        Collection<ChatService>  chatServices = clients.values();
        for(Session ch : sessionMap.values()){
            log.info("【当前用户sessionid】{}",ch.getId());
        }


        //连接上后给客户端一个消息
        sendMsg(session, "连接服务器成功！");
        log.info("新连接：{}", userId);
    }

    //关闭时执行
    @OnClose
    public void onClose() {
        clients.remove(this.userId);
        log.info("用户下线：{} ", this.userId);
        subOnlineCount();
    }

    //收到消息时执行
    @OnMessage
    public void onMessage(String message, Session session) throws IOException, ExecutionException, InterruptedException {
        log.info("服务器端收到来自用户{}的消息{},sessionId={}", this.userId, message,session.getId());  //  服务器端 收到
        clients.values().stream().forEach(x->System.out.println("<<<<<<<<<"+x.userId+">>>>>>>>>"));
        JSONObject jsonObject = JSON.parseObject(message);
        String textMessage = jsonObject.getString("message");
        String fromusername = jsonObject.getString("username");
        String tousername = jsonObject.getString("to");
        //String toUserNickName = jsonObject.getString("toUserNickName");
        //如果不是发给所有，那么就发给某一个人
        //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
        Map<String,Object> map1 = new HashMap<>();
        map1.put("messageType",4);
        map1.put("textMessage",textMessage);
        map1.put("fromusername",fromusername);
        //map1.put("myselfNickName",myselfNickName);   // 自己昵称
        // map1.put("toUserNickName",toUserNickName); // 接收人昵称
        if(tousername.equals("All")){
            map1.put("tousername","所有人");
            //sendMessageAll(JSON.toJSONString(map1),fromusername);.in
            log.info("发送给我所有人");
        }
        else{
            map1.put("tousername",tousername);
            try {
                if(session.isOpen()){
                    sendMessageTo(JSON.toJSONString(map1),tousername);
                }
            }catch (Exception e){
                e.printStackTrace();
                log.info(" 接收信息用户id为{}，推送消息失败，消息为{}",tousername,textMessage);
            }
        }
    }

    //  sessionMap 中存储的是 useID和session
    public void sendMessageTo(String message, String ToUserName) {
        if(StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(ToUserName)){
            //messageService = new MessageServiceImpl();
            messageService.save(message,userId,ToUserName);
            log.info("我的消息------入库,发送用户id是{},消息内容是{}，接收者id是{}",userId,ToUserName);
        }
        for (ChatService item : clients.values()) {
             log.info("遍历clients中的元素{}",item.userId);
             if(!clients.containsKey(ToUserName)){
                 log.info("................clients add 新元素{}...................",ToUserName);
                 clients.put(ToUserName,this);
                 log.info("................clients add 新元素{}...................",ToUserName);
             }
             // item.session.getOpenSessions().stream().filter($->$.getId() == sessionMap.get(ToUserName).getId()).findFirst().get().getAsyncRemote().sendText(message);

            if (item.userId.equals(ToUserName) ) {
                item.session.getAsyncRemote().sendText(message);
                //item.session.getOpenSessions().stream().filter($->$.getId() == sessionMap.get(ToUserName).getId()).findFirst().get().getAsyncRemote().sendText(message);
                log.info("我是{}，发消息给{}",userId,ToUserName);
                break;
            }


        }
    }


    //连接错误时执行
    @OnError
    public void onError(Session session, Throwable error) {
        log.debug("用户id为：{}的连接发送错误", this.userId);
        error.printStackTrace();
    }

    //统一的发送消息方法
    public synchronized void sendMsg(Session session, String msg) {
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
